package com.yehebl.orm.data.common.xml;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.yehebl.orm.data.common.IDao;
import com.yehebl.orm.data.common.dto.Page;
import com.yehebl.orm.data.common.dto.SimplePage;
import com.yehebl.orm.data.common.xml.dto.XmlSql;
import com.yehebl.orm.data.mysql.MySqlSqlManager;
import com.yehebl.orm.dto.ClassInfo;
import com.yehebl.orm.exception.ClassNotEntityException;
import com.yehebl.orm.manager.ReadClassManager;


/**
 * query xml 查询默认操作
 */
public abstract class AQueryXmlSql {

	public AQueryXmlSql() {
	}

	/**
	 * 对应xml 的sqlName
	 */
	private String sqlName="defaultXmlSql";
	
	
	/**
	 * 直接使用sql
	 */
	private String sql;

	/**
	 * 页码
	 */
	private Integer page;

	/**
	 * 每页长度
	 */
	private Integer size;


	/**
	 *  pageType null或者1:分页和数据,2:数据,3:分页
	 */
	private Integer pageType;

	private StringBuilder prefixSql;


	private IDao dao;

	/**
	 * 命名条件
	 */
	private Map<String, Object> params = new HashMap<String, Object>();

	/**
	 * 拼接sql
	 */
	private Map<String, String> appendSql = new HashMap<String, String>();


	/**
	 * 
	 * @param clazz   返回的类
	 * @return 返回单类
	 */
	public <T> T get(Class<T> clazz) {
		return dao.getBySqlName(this.getSqlName(), this, clazz);
	}


	/**
	 * 获取单个值，只获得第一行第一列
	 */
	public Object getObject() {
		return dao.getObjectBySqlName(this.getSqlName(), this);
	}

	/**
	 * 
	 * @param clazz   返回的类类型
	 * @return 返回 list
	 */
	public <T> List<T> find(Class<T> clazz) {
		if (this.getPage() != null && this.getSize() != null) {
			return dao.findBySqlName(this.getSqlName(), this, this.getPage(), this.getSize(), clazz);
		} else if (this.getSize() != null) {
			return dao.findBySqlName(this.getSqlName(), this, this.getSize(), clazz);
		}

		return dao.findBySqlName(this.getSqlName(), this, clazz);
	}


	/**
	 * 总条数自动生成sql
	 * 
	 * 
	 * @param clazz   返回类型
	 * @return
	 */
	public <T> Page<T> findPage(Class<T> clazz) {
		if(page==null||size==null) {
			throw new RuntimeException("page 或 size 不能为空");
		}
		return dao.findPageBySqlName(this.getSqlName(), this, this.page, this.size,this.pageType, clazz);
	}
	
	/**
	 * 总条数自动生成sql
	 * 
	 * 
	 * @param clazz   返回类型
	 * @return
	 */
	public <T> SimplePage<T> findSimplePage(Class<T> clazz) {
		if(page==null||size==null) {
			throw new RuntimeException("page 或 size 不能为空");
		}
		return dao.findSimplePageBySqlName(this.getSqlName(), this, this.page, this.size, clazz);
	}



	/**
	 * 
	 * @param
	 * @return 返回单类
	 */
	public <T> Map<String, Object> getMap() {
		return dao.getMapBySqlName(this.getSqlName(), this);
	}

	/**
	 * 
	 * @return 返回List
	 */
	public <T> List<Map<String, Object>> findMap() {
		if (this.getPage() != null && this.getSize() != null) {
			return dao.findMapBySqlName(this.getSqlName(), this, this.getPage(), this.getSize());
		} else if (this.getSize() != null) {
			return dao.findMapBySqlName(this.getSqlName(), this, this.getSize());
		}
		return dao.findMapBySqlName(this.getSqlName(), this);
	}



	public <T> T getOne(Class<T> clazz) {
		return dao.getOneBySqlName(sqlName,this, clazz);
	}

	/**
	 * 总条数自动生成sql
	 * 
	 * @return
	 */
	public Page<Map<String, Object>> findMapPage() {
		return dao.findMapPageBySqlName(this.getSqlName(), this, this.getPage() == null ? 1 : this.getPage().intValue(),
				this.getSize() == null ? 10 : this.getSize().intValue(),this.pageType);
	}

	public abstract StringBuilder getResultSql(XmlSql xmlSql, List<Object> list);

	public String getSqlName() {
		return sqlName;
	}

	public void setSqlName(String sqlName) {
		this.sqlName = sqlName;
	}

	public IDao getDao() {
		return dao;
	}

	public void setDao(IDao dao) {
		this.dao = dao;
	}

	/**
	 * 
	 * @param key
	 * @param object 不允许null 和空串
	 */
	public AQueryXmlSql addParams(String key, Object object) {
		if (object == null) {
			return this;
		}
		if (object instanceof String && "".equals(object.toString().trim())) {
			return this;
		}
		params.put(key, object);
		return this;
	}

	/**
	 * 
	 * @param key
	 * @param object 不允许null 和空串
	 */
	public AQueryXmlSql addLikeParams(String key, Object object) {
		if (object == null) {
			return this;
		}
		if (object instanceof String && "".equals(object.toString().trim())) {
			return this;
		}
		params.put(key, "%" + object + "%");
		return this;
	}

	/**
	 * 
	 * @param key
	 * @param object 不允许null 和空串
	 */
	public AQueryXmlSql addRlikeParams(String key, Object object) {
		if (object == null) {
			return this;
		}
		if (object instanceof String && "".equals(object.toString().trim())) {
			return this;
		}
		params.put(key, object + "%");
		return this;
	}

	/**
	 * 
	 * @param key
	 * @param object 不允许null 和空串
	 */
	public AQueryXmlSql addLlikeParams(String key, Object object) {
		if (object == null) {
			return this;
		}
		if (object instanceof String && "".equals(object.toString().trim())) {
			return this;
		}
		params.put(key, "%" + object);
		return this;
	}

	public AQueryXmlSql addParamsIsBlank(String key, Object object) {
		params.put(key, object);
		return this;
	}

	/**
	 * 
	 * @param key
	 */
	public AQueryXmlSql addAppend(String key, String str) {
		if (null == str || str.trim().equals("")) {
			return this;
		}
		appendSql.put(key, str);
		return this;
	}

	/**
	 * 
	 */
	public AQueryXmlSql addAppendIsBlank(String key, String str) {
		appendSql.put(key, str == null ? "" : str);
		return this;
	}

	/**
	 * 分页
	 * @param pageType null或者1:分页和数据,2:数据,3:分页
	 */
	public AQueryXmlSql limit(Integer page, Integer size,Integer pageType) {
		this.page = page < 1 ? 1 : page;
		this.size = size;
		this.pageType=pageType;
		return this;
	}


	/**
	 * 分页
	 *
	 * @return
	 */
	public AQueryXmlSql limit(Integer page, Integer size) {
		this.page = page < 1 ? 1 : page;
		this.size = size;
		return this;
	}

	/**
	 * 分页
	 * 
	 * @return
	 */
	public AQueryXmlSql limit(Page<?> page) {
		return limit(page.getPage(), page.getSize());
	}

	/**
	 * 分页
	 * 
	 * @return
	 */
	public AQueryXmlSql limit(Integer size) {
		this.size = size;
		return this;
	}

	protected ClassInfo getClassInfo(Class<?> clazz) {
		ClassInfo classInfo = ReadClassManager.map.get(clazz.getName());
		if (classInfo == null) {
			throw new ClassNotEntityException(clazz);
		}
		return classInfo;
	}

	/**
	 * 查询别名
	 * 
	 * @return
	 */
	public AQueryXmlSql select(Class<?> clazz, String alias) {
		final ClassInfo ci = getClassInfo(clazz);
		String sql = MySqlSqlManager.getColumn(ci, alias);
		if (this.getPrefixSql() == null) {
			this.setPrefixSql(new StringBuilder());
			this.getPrefixSql().append(sql);
		} else {
			this.getPrefixSql().append("," + sql);
		}
		return this;
	}

	/**
	 * 查询别名
	 * 
	 * @return
	 */
	public AQueryXmlSql select(Class<?> clazz, String alias, String objectName) {
		final ClassInfo ci = getClassInfo(clazz);
		String sql = MySqlSqlManager.getColumn(ci, alias, objectName);
		if (this.getPrefixSql() == null) {
			this.setPrefixSql(new StringBuilder());
			this.getPrefixSql().append(sql);
		} else {
			this.getPrefixSql().append("," + sql);
		}
		return this;
	}

	public Integer getPage() {
		return page;
	}

	public void setPage(Integer page) {
		this.page = page;
	}

	public Integer getSize() {
		return size;
	}

	public void setSize(Integer size) {
		this.size = size;
	}

	public Map<String, Object> getParams() {
		return params;
	}

	public void setParams(Map<String, Object> params) {
		this.params = params;
	}

	public Map<String, String> getAppendSql() {
		return appendSql;
	}

	public void setAppendSql(Map<String, String> appendSql) {
		this.appendSql = appendSql;
	}

	public StringBuilder getPrefixSql() {
		return prefixSql;
	}

	public void setPrefixSql(StringBuilder prefixSql) {
		this.prefixSql = prefixSql;
	}


	public String getSql() {
		return sql;
	}


	public void setSql(String sql) {
		this.sql = sql;
	}
	
	
	
	

}
